import ustruct as struct

class RAMBlockDev:
    def __init__(self, block_size, num_blocks):
        self.block_size = block_size
        self.data = bytearray(block_size * num_blocks)

    def readblocks(self, block_num, buf, offset=0):
        addr = block_num * self.block_size + offset
        for i in range(len(buf)):
            buf[i] = self.data[addr + i]

    def writeblocks(self, block_num, buf, offset=None):
        if offset is None:
            for i in range(len(buf) // self.block_size):
                self.ioctl(6, block_num + i)
            offset = 0
        addr = block_num * self.block_size + offset
        for i in range(len(buf)):
            self.data[addr + i] = buf[i]

    def ioctl(self, op, arg):
        if op == 4: # block count
            return len(self.data) // self.block_size
        if op == 5: # block size
            return self.block_size
        if op == 6: # block erase
            return 0

class AcdpSPI:
    def __init__(self, spi):
        self.spi = spi
    
    def send(self, buf):
        header = bytearray(struct.pack('i', len(buf)))
        self.spi.write(header)
        self.spi.write(buf)

    def recv(self):
        header = bytearray(4)
        self.spi.readinto(header)
        header_length = struct.unpack('i', bytes(header))[0]
        buf = bytearray(header_length)
        self.spi.readinto(buf)
        return buf

class AcdpBlockDev(AcdpSPI):
    def __init__(self, spi, block_id, block_size=None, num_blocks=None):
        self.spi = spi
        self.block_id = block_id
        if (block_size is None) or (num_blocks is None):
            block_size, num_blocks = self.deviceinfo()
        self.block_size = block_size
        self.data = bytearray(block_size * num_blocks)

    def deviceinfo(self):

        pass

    def readblocks(self, block_num, buf, offset=0):
        pass

    def writeblocks(self, block_num, buf, offset=None):
        pass

    def ioctl(self, op, arg):
        if op == 4: # block count
            return len(self.data) // self.block_size
        if op == 5: # block size
            return self.block_size
        if op == 6: # block erase
            return 0